#include "ota_version.h"

#define OTA_VERSION_INFO_URL "http://192.168.56.88:8000/ota_server/gateway_version_info.json"
#define OTA_SW_URL "http://192.168.56.88:8000/ota_server/gateway"
#define OTA_SW_TMP_PATH "/usr/bin/gateway.update"
#define OTA_SW_OLD "/usr/bin/gateway.old"

version_t *ota_version_parse_version_info(char *json)
{
    cJSON *root = cJSON_Parse(json);
    if (root == NULL)
    {
        log_error("cJSON_Parse error");
        return NULL;
    }
    version_t *version = (version_t *)malloc(sizeof(version_t));

    version->major = cJSON_GetObjectItem(root, "major")->valueint;
    version->minor = cJSON_GetObjectItem(root, "minor")->valueint;
    version->patch = cJSON_GetObjectItem(root, "patch")->valueint;

    if (cJSON_GetObjectItem(root, "sha1"))
    {
        version->sha1 = strdup(cJSON_GetObjectItem(root, "sha1")->valuestring);
    }

    cJSON_Delete(root);
    return version;
}

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/sha.h>

char *ota_version_get_sha1(char *path)
{
    FILE *file = fopen(path, "rb");
    if (!file)
    {
        perror("fopen");
        return NULL;
    }

    unsigned char hash[SHA_DIGEST_LENGTH];
    SHA_CTX sha_ctx;
    unsigned char buffer[4096];
    size_t bytes_read;

    SHA1_Init(&sha_ctx);

    while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0)
    {
        SHA1_Update(&sha_ctx, buffer, bytes_read);
    }

    SHA1_Final(hash, &sha_ctx);
    fclose(file);

    // 分配 41 字节，40位十六进制字符 + '\0'
    char *output = malloc(SHA_DIGEST_LENGTH * 2 + 1);
    if (!output)
        return NULL;

    for (int i = 0; i < SHA_DIGEST_LENGTH; i++)
    {
        sprintf(output + (i * 2), "%02x", hash[i]);
    }
    output[SHA_DIGEST_LENGTH * 2] = '\0';

    return output; // 记得调用方 free()
}

gate_status_t ota_version_check(void)
{
    uint8_t *version_info_json = ota_http_getText(OTA_VERSION_INFO_URL);

    version_t *version_new = ota_version_parse_version_info(version_info_json);
    version_t *version_cur = ota_version_parse_version_info(CUR_VERSION_INFO);
    printf("version_new: %d.%d.%d\n", version_new->major, version_new->minor, version_new->patch);
    printf("version_cur: %d.%d.%d\n", version_cur->major, version_cur->minor, version_cur->patch);

    // 不需要更新提前结束
    if (version_new->major < version_cur->major ||
        (version_new->major == version_cur->major && version_new->minor < version_cur->minor) ||
        (version_new->major == version_cur->major && version_new->minor == version_cur->minor && version_new->patch <= version_cur->patch))
    {
        log_info("已经是最新版本, 不需要更新");
        return ERROR;
    }
    log_info("开始更新");
    // 下载远程文件
    gate_status_t status = ota_http_download(OTA_SW_URL, OTA_SW_TMP_PATH);
    if (status != OK)
    {
        log_error("下载失败");
        return status;
    }
    char *sha1 = ota_version_get_sha1(OTA_SW_TMP_PATH);
    printf("sha1: %s\n", sha1);
    if (strcmp(sha1, version_new->sha1) != 0)
    {
        log_error("sha1校验失败");
        return ERROR;
    }

    log_info("下载成功");

    free(version_new);
    free(version_cur);
    free(sha1);

    // 会有一个开机自启动的脚本: 检测有没有新下载的程序, 如果有, 则执行下载的
    reboot(RB_AUTOBOOT);
    return OK;
}

void ota_version_auto_update(void)
{
    ota_version_check();
    while (1)
    {
        time_t now = time(NULL);
        struct tm *t = localtime(&now);
        if (t->tm_hour == 11 && t->tm_min == 17)
        {
            ota_version_check();
        }
        sleep(60);
    }
}
